//-----------------------------------------------------------------------
// <copyright file="AddCertificate.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Giles Knap</author>
// <email>gilesk</email>
// <date>2005-07-08</date>
// <summary>
//    Adds an Http Header to a web site
//</summary>
//-----------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.Certificates
{
    using System;
    using System.Xml;
    using System.Globalization;
    using System.Net;
    using System.Security.Cryptography.X509Certificates;

    using Microsoft.Sdc.Tasks.Configuration.Web;
    using Microsoft.Build.Framework;

    /// <summary>
    /// Imports a certificate (and private key if required) from a pfx or cer file. Note that 
    /// repeated imports of the same certificate will not result in multiple copies being installed
    /// (but todo in this name space: FindCertificates, DeleteCertificate ...)
    /// </summary>
    /// <remarks>
    /// <code><![CDATA[<Certificates.AddCertificate 
    ///     FileName="fileName" 
    ///     Password="password"
    ///     StoreName="storeName"
    ///     MachineStore="machineStore"
    ///     Thumbprint="thumbprint" />]]></code>
    /// <para>where:</para>
    /// <para><i>storeName</i></para>
    /// <para>Name of certificate store in which to place new certificate, defaults to "MY" <br />
    /// Should be one of:- <br />
    /// AddressBook:          The X509 certificate store for other users. <br />
    /// AuthRoot:             The X509 certificate store for third-party certificate authorities (CAs). <br />
    /// CertificateAuthority: The X509 certificate store for intermediate certificate authorities (CAs). <br />
    /// Disallowed:           The X509 certificate store for revoked certificates. <br />
    /// My:                   The X509 certificate store for personal certificates. <br />
    /// Root:                 The X509 certificate store for trusted root certificate authorities (CAs). <br />
    /// TrustedPeople:        The X509 certificate store for directly trusted people and resources. <br />
    /// TrustedPublisher:     The X509 certificate store for directly trusted publishers. <br />
    /// </para>
    /// <para><i>password</i></para>
    /// <para>password for the pfx file from which the certificate is to be imported, defaults to blank</para>
    /// <para><i>machineStore</i></para>
    /// <para>set to true if the certificate is to be installed in the machine store, false for the user store, defaults to false</para>
    /// <para><i>fileName</i></para>
    /// <para>Full path to pfx file for import</para>
    /// <para><i>thumbprint (Ouput)</i></para>
    /// <para>outputs the certificate thumbprint. Used to uniquely identify certificate in further tasks.</para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <Target Name="Test" >
    ///         <AddCertificate
    ///             FileName=""
    ///             Password="xyzzy"
    ///             StorePrivateKey="true"
    ///             MachineStore="false">
    ///          <Output TaskParameter="thumbprint" PropertyName="NewCertHash"/>
    ///         </AddCertificate>
    ///     </Target>
    /// </Project>
    /// ]]></code>    
    /// </example>    
    public class AddCertificate : TaskBase
    {
        private string storeName;
        private string fileName;
        private string password;
        private bool machineStore = false;
        private string thumbprint;

        /// <summary>
        /// Initializes a new instance of the AddMimeTypeToWebSite class.
        /// </summary>
        public AddCertificate()
        {
        }

        /// <summary>
        /// MachineStore
        /// </summary>
        [Required]
        public bool MachineStore
        {
            get { return this.machineStore; }
            set { this.machineStore = value; }
        }

        /// <summary>
        /// Thumbprint
        /// </summary>
        [Output]
        public string Thumbprint
        {
            get { return (this.thumbprint == null ? String.Empty : this.thumbprint); }
            set { this.thumbprint = value; }
        }

        /// <summary>
        /// StoreName
        /// </summary>
        public string StoreName
        {
            get { return (this.storeName == null ? String.Empty : this.storeName); }
            set { this.storeName = value; }
        }

        /// <summary>
        /// Host name for website we are adding the filter to
        /// </summary>
        /// <value>A valid host name</value>
        [Required]
        public string FileName
        {
            get { return (this.fileName == null ? String.Empty : this.fileName); }
            set { this.fileName = value; }
        }

        /// <summary>
        /// Password
        /// </summary>
        public string Password
        {
            get { return (this.password == null ? String.Empty : this.password); }
            set { this.password = value; }
        }

        /// <summary>
        /// Performs the action of this task.
        /// </summary>
        protected override void InternalExecute()
        {
            #region Execute code

            if (this.storeName == null || this.storeName.Length == 0)
            {
                this.storeName = "MY";
            }

            this.Log.LogMessage(String.Format(CultureInfo.InvariantCulture, "Importing certificate file '{0}' to {1} store...", this.fileName, this.storeName));

            X509Certificate2 cert = new X509Certificate2();
            X509KeyStorageFlags keyflags;

            if (this.machineStore) keyflags = X509KeyStorageFlags.MachineKeySet;
            else keyflags = X509KeyStorageFlags.DefaultKeySet;
            keyflags |= X509KeyStorageFlags.PersistKeySet;

            cert.Import(this.fileName, this.password, keyflags);

            StoreLocation locationFlag;
            if (this.machineStore)
            {
                locationFlag = StoreLocation.LocalMachine;
            }
            else
            {
                locationFlag = StoreLocation.CurrentUser;
            }

            X509Store store = new X509Store(this.storeName, locationFlag);
            store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);
            store.Add(cert);
            store.Close();

            this.thumbprint = cert.Thumbprint;
            this.Log.LogMessage(String.Format(CultureInfo.InvariantCulture, "Certificate imported, thumbprint = '{0}'", this.thumbprint));

            #endregion
        }
    }
}

